package com.gitee.wsl.mathematics.vector.ext

import com.gitee.wsl.mathematics.base.NumberMapping4
import com.gitee.wsl.mathematics.coordinate.d2.Coordinate2
import com.gitee.wsl.mathematics.coordinate.d3.Coordinate3
import com.gitee.wsl.mathematics.vector.vec2.Vector2
import com.gitee.wsl.mathematics.vector.vec3.Vector3

import com.gitee.wsl.mathematics.vector.vec4.Vector4

/** Calculate a cross-product of [this], [b], and [c] and reduce it by [out]. */
private inline fun <T:Number,R> Vector4<T,*>.cross(b: Vector4<T,*>, c: Vector4<T,*>, out: NumberMapping4<T,R>): R {
    val s1 = b.x * c.y - b.y * c.x
    val s2 = b.x * c.z - b.z * c.x
    val s3 = b.x * c.w - b.w * c.x
    val s4 = b.y * c.z - b.z * c.y
    val s5 = b.y * c.w - b.w * c.y
    val s6 = b.z * c.w - b.w * c.z

    return out(
            y * s6 - z * s5 + w * s4,
            -(x * s6) + z * s3 - w * s2,
            x * s5 - y * s3 + w * s1,
            -(x * s4) + y * s2 - z * s1
        )
}

/** Calculate a cross-product of [this], [b], and [c] and set it to [out]. */
fun <T:Number,V:Vector4<T,V>> Vector4<T,V>.cross(b: Vector4<T,*>, c: Vector4<T,*>) = cross(b, c){a,b,c,d->create(a,b,c,d)}

//fun <T:Number,V:Vector4<T,V>> V.cross(b: Vector4<T,*>, c: Vector4<T,*>) = cross(b, c){a,b,c,d->create(a,b,c,d)}

infix fun<T:Number> Vector2<T, *>.cross(other: Vector2<T, *>):T = x * other.x - y * other.y

infix fun<T:Number> Vector2<T, *>.cross(other: Vector3<T, *>)  = (other cross this)

infix fun<T:Number> Vector3<T, *>.cross(other: Vector2<T, *>) = create(-z * other.y, z * other.x, x * other.y - y * other.x) as Vector3<T, *>

infix fun<T:Number,V: Vector3<T, V>> Vector3<T, V>.cross(other: Vector3<T, *>):V = create(
    y * other.z - z * other.y,
    z * other.x - x * other.z,
    x * other.y - y * other.x
)